package com.jml.service;

import com.jml.constant.RegisterConstant;
import com.jml.entity.ServiceInstance;
import com.jml.req.parameter.ReqInfoDTO;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Component
public class JmlRegisterContainer {
    private static final Log log = LogFactory.getLog(JmlRegisterContainer.class);
    /**
     * key是服务的名字，value是服务的地址列表,TreeSetbiaosh
     */
    private static volatile Map<String, TreeSet<ServiceInstance>> mapAddres = new ConcurrentHashMap<>();

    public boolean put(ReqInfoDTO reqInfo) {
        //1.先判断容器 是否已经注册该服务
        String serviceName = reqInfo.getServiceName();
        TreeSet<ServiceInstance> serviceInstances = mapAddres.get(serviceName);
        if (serviceInstances == null) {  // 使用双重检验锁  判断保证线程安全性问题
            synchronized (this) {
                if (serviceInstances == null) {
                    serviceInstances = new TreeSet<ServiceInstance>();
                }
            }
            mapAddres.put(serviceName, serviceInstances);
        }
        // 将接口地址存放到 服务注册中心中，要重写hashCodehe equals方法
        ServiceInstance serviceInstance = new ServiceInstance(serviceName, reqInfo.getServiceAddres(),
                System.currentTimeMillis());
        return serviceInstances.add(serviceInstance);
    }

    public Map<String, TreeSet<ServiceInstance>> getMapAddres() {
        return mapAddres;
    }

    /**
     * 注册中心服务剔除
     */
    class Heartbeat implements Runnable {
        @Override
        public void run() {
            mapAddres.forEach((k, v) -> {
                TreeSet<ServiceInstance> serviceInstances = mapAddres.get(k);
                serviceInstances.forEach((serviceInstance) -> {
                    // 续约时间  22:00:10
                    long currentTimeMillis = System.currentTimeMillis();
                    //上次续约的时间
                    long lastRenewalTime = serviceInstance.getLastRenewalTime();
                    //超过5s没有续约就剔除服务
                    if (currentTimeMillis - lastRenewalTime > RegisterConstant.DELETEIP_TIMEOUT) {
                        log.info("服务名称：" + serviceInstance.getServiceName() + "," +
                                "服务地址" + serviceInstance.getServiceAddres() + ",当前系统时间:" + currentTimeMillis
                                + ",该服务上一次续约时间" + lastRenewalTime + "服务被剔除.");
                        //续约超时，直接移除 剔除该地址
                        serviceInstances.remove(serviceInstance);
                    }
                });
            });
        }
    }

    private ScheduledExecutorService scheduledService = Executors.newSingleThreadScheduledExecutor();

    public JmlRegisterContainer() {
        // 服务注册中心每隔3s 检查地址是否宕机
        scheduledService.scheduleAtFixedRate(new Heartbeat(), 3, 3, TimeUnit.SECONDS);
    }
}
